using System;
using System.Collections.Generic;
using System.Text;
using NSvn.Common;
using NSvn.Core;
using System.IO;

namespace Stratman.DesktopProcess.DatabaseSynchronizer
{
    /// <summary>
    /// Provides an interface to an SVN repository.
    /// </summary>
    public class SvnSccProvider : ISccProvider
    {
        /// <summary>
        /// Object that we are to use for all of our operations on the client side.
        /// </summary>
        protected Client svnClient = new Client();
        /// <summary>
        /// List of SVN admin directories.
        /// </summary>
        protected List<string> adminDirectories = new List<string>();

        /// <summary>
        /// Default constructor that populates the list of SVN admin directories.
        /// </summary>
        public SvnSccProvider()
        {
            adminDirectories.Add(".svn");
            adminDirectories.Add("_svn");
        }

        /// <summary>
        /// Checks to see if a given file is under source control.
        /// </summary>
        /// <param name="clientPath">
        /// Path to the file that we are to check.
        /// </param>
        /// <returns>
        /// True if the file is under source control, false otherwise.
        /// </returns>
        public bool IsUnderSourceControl(string clientPath)
        {
            return (svnClient.SingleStatus(clientPath).Entry != null);
        }

        /// <summary>
        /// Checks to see if a given file is checked out; returns true since SVN doesn't require
        /// exclusive checkouts.
        /// </summary>
        /// <param name="clientPath">
        /// Path to the file that we are to check.
        /// </param>
        /// <returns>
        /// True, always.
        /// </returns>
        public bool IsCheckedOut(string clientPath)
        {
            return true;
        }

        /// <summary>
        /// Checks out a file from the repository; does nothing since SVN doesn't require exclusive
        /// checkouts.
        /// </summary>
        /// <param name="clientPath">
        /// Path to the file that we are to check out.
        /// </param>
        public void CheckOut(string clientPath)
        {
        }

        /// <summary>
        /// Adds a given file to the repository.
        /// </summary>
        /// <param name="clientPath">
        /// Path to the file that we are to add to the repository.
        /// </param>
        public void Add(string clientPath)
        {
            SetAdminDirectory(clientPath);
            svnClient.Add(clientPath, Recurse.None);
        }

        /// <summary>
        /// Deletes a given file from the repository.
        /// </summary>
        /// <param name="clientPath">
        /// Path to the file that we are to delete from the repository.
        /// </param>
        public void Delete(string clientPath)
        {
            SetAdminDirectory(clientPath);
            svnClient.Delete(new string[] { clientPath }, true);
        }

        /// <summary>
        /// Returns a list of admin directories for SVN, including ".svn" and "_svn".
        /// </summary>
        public List<string> AdminDirectories
        {
            get
            {
                return adminDirectories;
            }
        }

        /// <summary>
        /// Sets the admin directory of the client object appropriately, depending on whether
        /// there's a ".svn" directory or a "_svn" directory present.
        /// </summary>
        /// <param name="clientPath">
        /// Path to the file or directory for which we are to set the correct admin directory.
        /// </param>
        protected void SetAdminDirectory(string clientPath)
        {
            DirectoryInfo parentDirectory = null;

            if (File.Exists(clientPath))
                parentDirectory = new FileInfo(clientPath).Directory;

            else if (Directory.Exists(clientPath))
                parentDirectory = new DirectoryInfo(clientPath).Parent;

            if (parentDirectory != null && Directory.Exists(parentDirectory.FullName + "\\_svn"))
                Client.AdminDirectoryName = "_svn";
        }
    }
}
